package com.ruoyi.project.push;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gexin.rp.sdk.base.IBatch;
import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.PushResult;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.base.notify.Notify;
import com.gexin.rp.sdk.base.payload.APNPayload;
import com.gexin.rp.sdk.dto.GtReq;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.NotificationTemplate;
import com.gexin.rp.sdk.template.TransmissionTemplate;
import com.gexin.rp.sdk.template.style.Style0;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class AppPush {

    private static final Logger log = LoggerFactory.getLogger(AppPush.class);

    // STEP1：获取应用基本信息
    @Value ("${push.url}")
    private String url;
    @Value ("${push.user.appId}")
    private String userAppId;

    @Value ("${push.user.appKey}")
    private String userAppKey;

    @Value ("${push.user.masterSecret}")
    private String userMasterSecret;

    @Value ("${push.user.packet}")
    private String userPacket;


    // 对单个用户推送消息
    public IPushResult pushMsgToSingleByAppUser (String cid, Map <String, String> msg) {
        // 代表在个推注册的一个 app，调用该类实例的方法来执行对个推的请求
        IGtPush push = new IGtPush(this.userAppKey, this.userMasterSecret);
        // 创建信息模板
        TransmissionTemplate template = AppPush.getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(msg.get("title"),
                msg.get("titleText"), "0", msg, this.userAppId, this.userAppKey, this.userPacket
        );
        //定义消息推送方式为，单推
        SingleMessage message = new SingleMessage();
        // 设置推送消息的内容
        message.setData(template);
        message.setOffline(true);// 设置消息离线，并设置离线时间
        message.setOfflineExpireTime(72 * 3600 * 1000); // 离线有效时间，单位为毫秒，可选
        // 设置推送目标
        Target target = new Target();
        target.setAppId(this.userAppId);
        // 设置cid
        target.setClientId(cid);
        log.info("个推cid返回：" + cid);
        // 获得推送结果
        IPushResult result = push.pushMessageToSingle(message, target);
        log.info("个推提交返回打印：" + JSONUtils.toJSONString(result.getResponse()));
        /*
         * 1. 失败：{result=sign_error}
         * 2. 成功：{result=ok, taskId=OSS-0212_1b7578259b74972b2bba556bb12a9f9a, status=successed_online}
         * 3. 异常
         */
        return result;
    }


    public IPushResult pushMsgToMany (List <String> cids, Map <String, String> msg) {
        IGtPush push = new IGtPush(this.userAppKey, this.userMasterSecret);
        // 创建信息模板
        NotificationTemplate template = this.getNotifacationTemplate(this.userAppId, this.userAppKey, msg);
        //设置批量群发
        IBatch batch = push.getBatch();
        //群发消息
        SingleMessage message = new SingleMessage();
        // 设置推送消息的内容
        message.setData(template);
        message.setOffline(true);// 设置消息离线，并设置离线时间
        message.setOfflineExpireTime(72 * 3600 * 1000); // 离线有效时间，单位为毫秒，可选
        try {
            for (String cid : cids) {
                if (StringUtils.isNotBlank(cid)) {
                    // 设置推送目标，填入appid和clientId
                    Target target = new Target();
                    target.setAppId(this.userAppId);
                    target.setClientId(cid);
                    batch.add(message, target);
                }
            }
            IPushResult submit = batch.submit();
            log.info("个推提交返回打印：" + JSONUtils.toJSONString(submit.getResponse()));
            return submit;
        } catch (Exception e) {
            log.info("个推发送失败", e);
            return null;
        }
    }

    public IPushResult pushMsgToManyByAppPacket (List <String> cids, Map <String, String> msg) {
        return this.pushMsgToManyByAppPacket(cids, msg, true);
    }

    public IPushResult pushMsgToManyByAppPacket (List <String> cids, Map <String, String> msg, Boolean offline) {
        IGtPush push = new IGtPush(this.userAppKey, this.userMasterSecret);
        // 创建信息模板
        TransmissionTemplate template = AppPush.getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(msg.get("title"),
                msg.get("titleText"), "0", msg, this.userAppId, this.userAppKey, this.userPacket
        );
        //设置批量群发
        IBatch batch = push.getBatch();
        //群发消息
        SingleMessage message = new SingleMessage();
        // 设置推送消息的内容
        message.setData(template);
        message.setOffline(offline);// 设置消息离线，并设置离线时间
        message.setOfflineExpireTime(72 * 3600 * 1000); // 离线有效时间，单位为毫秒，可选
        try {
            for (String cid : cids) {
                if (StringUtils.isNotBlank(cid)) {
                    // 设置推送目标，填入appid和clientId
                    Target target = new Target();
                    target.setAppId(this.userAppId);
                    target.setClientId(cid);
                    batch.add(message, target);
                    batch.submit();
                }
            }
            IPushResult submit = new PushResult();
            return submit;
        } catch (Exception e) {
            log.info("个推发送失败", e);
            return null;
        }
    }


    // 设置通知消息模板
    /*
     * 1. appId
     * 2. appKey
     * 3. 要传送到客户端的 msg
     * 3.1 标题栏：key = title,
     * 3.2 通知栏内容： key = titleText,
     * 3.3 穿透内容：key = transText
     */
    private NotificationTemplate getNotifacationTemplate (String appId, String appKey, Map <String, String> msg) {
        // 在通知栏显示一条含图标、标题等的通知，用户点击后激活您的应用
        NotificationTemplate template = new NotificationTemplate();
        // 设置appid，appkey
        template.setAppId(appId);
        template.setAppkey(appKey);
        // 穿透消息设置为，1 强制启动应用
        template.setTransmissionType(1);
        // 设置穿透内容
        template.setTransmissionContent(msg.get("transText"));
        // 设置style
        Style0 style = new Style0();
        // 设置通知栏标题和内容
        style.setTitle(msg.get("title"));
        style.setText(msg.get("titleText"));
        // 设置通知，响铃、震动、可清除
        style.setRing(true);
        style.setVibrate(true);
        style.setClearable(true);
        // 设置
        template.setStyle(style);

        return template;
    }


    /**
     * 获取同时有Android第三方推送及IOS推送功能的很透传消息
     *
     * @param title
     *         标题
     * @param body
     *         正文
     * @param badge
     *         IOS的角标数
     * @param customParam
     *         自定义属性
     *
     * @return
     */
    public static TransmissionTemplate getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload (String title, String body,
            String badge, Map <String, String> customParam, String appId, String appKey, String packet) {
        TransmissionTemplate template = new TransmissionTemplate();

        // 设置APPID与APPKEY
        template.setAppId(appId);
        template.setAppkey(appKey);

        // 透传消息设置，1为强制启动应用，客户端接收到消息后就会立即启动应用；2为等待应用启动
        template.setTransmissionType(2);
        template.setTransmissionContent(JSON.toJSONString(customParam)); // 透传内容

        // 第三方厂商推送
        template.set3rdNotifyInfo(get3rdNotifyInfo(title, body, customParam, packet));

        // 针对IOS，设置APNs
        template.setAPNInfo(getAPNPayload(title, body, badge, customParam)); // ios消息推送
        return template;
    }

    /**
     * 第三方厂商通知
     *
     * @param title
     *         标题
     * @param content
     *         正文
     * @param payload
     *         附带属性
     *
     * @return
     */
    private static Notify get3rdNotifyInfo (String title, String content, Map <String, String> payload, String packet) {
        Notify notify = new Notify();
        //notify.addHWExtKV("/message/android/target_user_type", 1);
        notify.setTitle(title);
        notify.setContent(content);
        notify.setType(GtReq.NotifyInfo.Type._intent);
        //intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component=com.bajiaostar.uuRunBiker;S.UP-OL-SU=true;S.title=123;S.content=123;S.payload=ceshi;end
        // /io.dcloud.PandoraEntry
        String intent = "intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component=" + packet + ";S.UP-OL-SU=true;S.title=" + title + ";S.content=" + content + ";S.payload=ceshi;end";
        log.debug(intent);
        notify.setIntent(intent);
        notify.setPayload(JSON.toJSONString(payload));
        return notify;
    }

    /**
     * IOS的APNs消息
     *
     * @param title
     * @param body
     * @param badge
     * @param customMsg
     *
     * @return
     */
    private static APNPayload getAPNPayload (String title, String body, String badge, Map <String, String> customMsg) {
        APNPayload payload = new APNPayload();
        // 在已有数字基础上加1显示，设置为-1时，在已有数字上减1显示，设置为数字时，显示指定数字
        if (badge != null && badge.trim().length() > 0) {
            payload.setAutoBadge(badge);
        }
        payload.setContentAvailable(1);
        // ios 12.0 以上可以使用 Dictionary 类型的 sound
        payload.setSound("default");
        //      payload.setCategory("$由客户端定义");
        if (customMsg != null) {
            for (Map.Entry <String, String> enty : customMsg.entrySet()) {
                payload.addCustomMsg(enty.getKey(), enty.getValue());
            }
        }
        //      payload.setAlertMsg(new APNPayload.SimpleAlertMsg("helloCCCC"));//简单模式APNPayload.SimpleMsg
        payload.setAlertMsg(getDictionaryAlertMsg(title, body)); // 字典模式使用APNPayload.DictionaryAlertMsg

        //      // 设置语音播报类型，int类型，0.不可用 1.播放body 2.播放自定义文本
        //      payload.setVoicePlayType(2);
        //      // 设置语音播报内容，String类型，非必须参数，用户自定义播放内容，仅在voicePlayMessage=2时生效
        //      // 注：当"定义类型"=2, "定义内容"为空时则忽略不播放
        //      payload.setVoicePlayMessage("定义内容");
        //
        //      // 添加多媒体资源
        //      payload.addMultiMedia(new MultiMedia().setResType(MultiMedia.MediaType.pic).setResUrl("资源文件地址").setOnlyWifi(true));

        return payload;
    }

    /**
     * IOS通知提示样式
     *
     * @param title
     * @param body
     *
     * @return
     */
    private static APNPayload.DictionaryAlertMsg getDictionaryAlertMsg (String title, String body) {
        APNPayload.DictionaryAlertMsg alertMsg = new APNPayload.DictionaryAlertMsg();
        alertMsg.setBody(body);
        //      alertMsg.setActionLocKey("显示关闭和查看两个按钮的消息");
        //      alertMsg.setLocKey("loc-key1");
        //      alertMsg.addLocArg("loc-ary1");
        //      alertMsg.setLaunchImage("调用已经在应用程序中绑定的图形文件名");
        // iOS8.2以上版本支持
        alertMsg.setTitle(title);
        //      alertMsg.setTitleLocKey("自定义通知标题");
        //      alertMsg.addTitleLocArg("自定义通知标题组");
        return alertMsg;
    }


    public static void main (String[] args) {

   /*     String userAppId = "rFHixd620k8CwhalE2piX7";
        String userAppKey = "OHz611b69z6X605KwbBK1";
        String userMasterSecret = "isWCgl952RAFH0lxZSUzY6";*/
        String userAppId = "LXFynKVsTy7FTULjPXqqv2";
        String userAppKey = "ArprJfbHb99KpNqMtsKA23";
        String userMasterSecret = "nCW1RNM7TM9zVbyZdsuTA";

        String userPacket = "com.bajiaostar.findjob";
        String cid = "d3af5882b2d6a48656bf542126a49306";
        //消息推送
        Map <String, String> msg = new HashMap <>();
        msg.put("title", "零工审核通知");
        // 当任务未通过审核
        msg.put("titleText", "零工审核通知");
        msg.put("transText", "");
        // 代表在个推注册的一个 app，调用该类实例的方法来执行对个推的请求
        IGtPush push = new IGtPush(userAppKey, userMasterSecret);
        // 创建信息模板
        TransmissionTemplate template = AppPush.getTransmissionTemplateWith3rdNotifyInfoAndAPNPayload(msg.get("title"),
                msg.get("titleText"), "0", msg, userAppId, userAppKey, userPacket
        );
        //定义消息推送方式为，单推
        SingleMessage message = new SingleMessage();
        // 设置推送消息的内容
        message.setData(template);
        message.setOffline(true);// 设置消息离线，并设置离线时间
        message.setOfflineExpireTime(72 * 3600 * 1000); // 离线有效时间，单位为毫秒，可选
        // 设置推送目标
        Target target = new Target();
        target.setAppId(userAppId);

        // 设置cid
        target.setClientId(cid);
        log.info("个推cid返回：" + cid);
        // 获得推送结果
        IPushResult result = push.pushMessageToSingle(message, target);
        System.out.println("个推提交返回打印：" + JSONObject.toJSONString(result));
        /*
         * 1. 失败：{result=sign_error}
         * 2. 成功：{result=ok, taskId=OSS-0212_1b7578259b74972b2bba556bb12a9f9a, status=successed_online}
         * 3. 异常
         */
    }


}
